package com.ymatou.iapi.optrade.testcase;

import java.math.BigDecimal;
import java.math.MathContext;
import java.math.RoundingMode;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.Date;
import java.util.List;
import java.util.stream.Collectors;

import org.json.JSONArray;
import org.json.JSONException;
import org.junit.After;
import org.junit.AfterClass;
import org.junit.Before;
import org.junit.BeforeClass;
import org.junit.Ignore;
import org.junit.Test;
import org.junit.experimental.categories.Category;

import com.ymatou.iapi.delivery.service.DeliveryService;
import com.ymatou.iapi.optrade.parameter.enums.AuthenticateFeeTypeEnum;
import com.ymatou.iapi.optrade.parameter.enums.AuthenticateFreightTypeEnum;
import com.ymatou.iapi.optrade.parameter.enums.CancelOrderTypeEnum;
import com.ymatou.iapi.optrade.parameter.enums.LogisticsTypeEnum;
import com.ymatou.iapi.optrade.parameter.req.BatchValidateRefundV2Req;
import com.ymatou.iapi.optrade.parameter.utill.Utils;
import com.ymatou.iapi.optrade.parameter.vo.MaxCanRefundAmountVo;
import com.ymatou.iapi.optrade.resp.Order;
import com.ymatou.iapi.optrade.resp.TradingServiceResp;
import com.ymatou.iapi.optrade.service.BatchValidateRefundV2Call;
import com.ymatou.iapi.optrade.service.RefundService;
import com.ymt.core.tool.Logger;
import com.ymt.utils.annotation.TestCase;
import com.ymt.utils.tag.P1;
import com.ymt.utils.tag.P3;
import com.ymttest.business.service.YMTTrading.TradingCallService;
import com.ymttest.business.service.YMTTrading.TradingPlaceAuthenticateCallService;
import com.ymttest.business.service.YMTTrading.TradingPlaceOrderCallService;
import com.ymttest.database.sharding.db.sharding.model.OrderDetailPo;
import com.ymttest.database.sharding.db.sharding.model.OrderPo;
import com.ymttest.database.sharding.db.sharding.model.RefundBillPo;
import com.ymttest.database.sharding.db.sqlwapper.OrderShardingWapper;
import com.ymttest.database.sqlwapper.DefaultWapper;
import com.ymttest.utils.DataUtil;

public class Ts_BatchValidateRefundV2 {

	private static BatchValidateRefundV2Req batchValidateRefundReq;
	private static BatchValidateRefundV2Call batchApplyvalidationCall;
	private static OrderShardingWapper orderShardingWapper = new OrderShardingWapper();

	@BeforeClass
	public static void setUp() {
		Logger.createResultFile("批量退货退款申请校验接口");
	}

	@Before
	public void caseUp() {
		batchValidateRefundReq = new BatchValidateRefundV2Req();
		batchApplyvalidationCall = new BatchValidateRefundV2Call();
	}

	@AfterClass
	public static void tearDown() {
		Logger.generateResult(batchApplyvalidationCall.getOpurl());
		orderShardingWapper.activeDeadCommunicationsLink(orderShardingWapper);
	}

	@After
	public void caseDown() {
		Logger.end();
	}

	/**
	 * 计算商品最大可退金额
	 * 
	 * @param po
	 * @return
	 */
	public static BigDecimal getOrderDetailPaidAmountExcludeFreight(
			OrderDetailPo po, int productCount) {

		BigDecimal refundAmount = Utils.zeroIfNull(po.getProductPrice())
				.multiply(new BigDecimal(po.getProductCount()))
				.add(Utils.zeroIfNull(po.getDiscount()))
				.subtract(Utils.zeroIfNull(po.getYmtCouponAmount()))
				.subtract(Utils.zeroIfNull(po.getSellerCouponAmount()))
				.subtract(Utils.zeroIfNull(po.getPromotionAmount()))
				.subtract(Utils.zeroIfNull(po.getThirdpartyDiscount()))
				.subtract(Utils.zeroIfNull(po.getYmtPromotionAmount()));

		if (po.getProductCount() != productCount) {

			refundAmount = refundAmount
					.divide(new BigDecimal(po.getProductCount()),
							MathContext.DECIMAL32)
					.setScale(2, RoundingMode.DOWN)
					.multiply(new BigDecimal(productCount));

		}

		return refundAmount;
	}

	/**
	 * 计算商品最大可退运费
	 * 
	 * @param po
	 * @return
	 */
	public static BigDecimal getMaxCanRefundFreight(Order order,
			BigDecimal productFreight) {

		long orderId = order.getOrderId();

		if (BigDecimal.ZERO.compareTo(productFreight) == 0) {

			return BigDecimal.ZERO;

		}

		List<RefundBillPo> res = orderShardingWapper
				.selectRefundBillListByOrderId(orderId);

		BigDecimal freight = res
				.stream()
				.filter(r -> r.getRefundBillStatus() == 1
						|| r.getRefundBillStatus() == 10)
				.map(f -> f.getFreight())
				.reduce(BigDecimal.ZERO, BigDecimal::add);

		return order.getOrderFreight().subtract(freight);

	}

	/**
	 * 
	 * @param order
	 * @param orderDetailPoList
	 * @param maxCanRefundAmountVosReq
	 * @throws JSONException
	 */
	private void verify(Order order, List<OrderDetailPo> orderDetailPoList,
			List<MaxCanRefundAmountVo> maxCanRefundAmountVosReq)
			throws JSONException {

		Logger.verifyEquals("true",
				batchApplyvalidationCall.getString("success"), "验证返回码");
		JSONArray maxCanRefundAmountVosResp = batchApplyvalidationCall
				.getMaxCanRefundAmountVos();

		for (int i = 0; i < maxCanRefundAmountVosReq.size(); i++) {
			BigDecimal maxCanRefundAmount = getOrderDetailPaidAmountExcludeFreight(
					orderDetailPoList.get(i), maxCanRefundAmountVosReq.get(i)
							.getApplyRefundCount());

			BigDecimal maxCanRefundFreight = getMaxCanRefundFreight(order,
					orderDetailPoList.get(i).getFreight());

			DataUtil.verifyDecimalEquals(maxCanRefundAmount,
					new BigDecimal(maxCanRefundAmountVosResp.getJSONObject(i)
							.optString("maxCanRefundAmount")),
					"验证maxCanRefundAmount");

			// 如果不是第一个商品，其他所有商品的运费都为0，第一个商品的运费为所有商品的运费总和
			if (i == 0) {
				DataUtil.verifyDecimalEquals(
						maxCanRefundFreight,
						new BigDecimal(maxCanRefundAmountVosResp.getJSONObject(
								i).optString("maxCanRefundFreight")),
						"验证maxCanRefundFreight");
			} else {
				DataUtil.verifyDecimalEquals(
						new BigDecimal(0),
						new BigDecimal(maxCanRefundAmountVosResp.getJSONObject(
								i).optString("maxCanRefundFreight")),
						"验证maxCanRefundFreight");
			}
		}
	}

	/**
	 * 
	 * @param order
	 * @param orderDetailPoList
	 * @param maxCanRefundAmountVosReq
	 * @param noFreight
	 * @throws JSONException
	 */
	private void verify(Order order, List<OrderDetailPo> orderDetailPoList,
			List<MaxCanRefundAmountVo> maxCanRefundAmountVosReq,
			boolean noFreight) throws JSONException {

		Logger.verifyEquals("true",
				batchApplyvalidationCall.getString("success"), "验证返回码");
		JSONArray maxCanRefundAmountVosResp = batchApplyvalidationCall
				.getMaxCanRefundAmountVos();

		BigDecimal maxCanRefundAmount = getOrderDetailPaidAmountExcludeFreight(
				orderDetailPoList.get(1), maxCanRefundAmountVosReq.get(0)
						.getApplyRefundCount());

		BigDecimal maxCanRefundFreight = getMaxCanRefundFreight(order,
				orderDetailPoList.get(1).getFreight());

		DataUtil.verifyDecimalEquals(maxCanRefundAmount,
				new BigDecimal(maxCanRefundAmountVosResp.getJSONObject(0)
						.optString("maxCanRefundAmount")),
				"验证maxCanRefundAmount");

		DataUtil.verifyDecimalEquals(maxCanRefundFreight,
				new BigDecimal(maxCanRefundAmountVosResp.getJSONObject(0)
						.optString("maxCanRefundFreight")),
				"验证maxCanRefundFreight");
	}

	@Test
	@Category(P1.class)
	@TestCase
	public void Tc_BatchValidateRefundV2_001() {
		Logger.start(true, "用户下单后未支付申请效验");
		try {
			// 创建订单
			Logger.comment("前置数据准备");

			TradingServiceResp placeOrderResp = TradingPlaceOrderCallService
					.placeOrderWithTwoProcutInOneOrder(false, false);
			long orderId = placeOrderResp.getOrderList().get(0).getOrderId();

			Logger.comment("前置数据准备结束");

			// 构造最大可退货退款商品列表
			List<MaxCanRefundAmountVo> maxCanRefundAmountVos = buildMaxCanRefundAmountVoList(placeOrderResp);

			batchValidateRefundReq.setApplyRefundAmount(BigDecimal.ONE);
			batchValidateRefundReq
					.setMaxCanRefundAmountVos(maxCanRefundAmountVos);
			batchValidateRefundReq.setOrderId(orderId);

			batchApplyvalidationCall.setData(batchValidateRefundReq);
			batchApplyvalidationCall.callService();

			Logger.verifyEquals("false",
					batchApplyvalidationCall.getString("success"), "验证返回码");

			Logger.verifyEquals("ERR_CONDITION_NOTMATCH",
					batchApplyvalidationCall.getString("errorCode"), "验证返回码");

			Logger.verifyEquals(String.format("当前订单状态不允许发起退款[%s]", orderId),
					batchApplyvalidationCall.getString("errorMessage"),
					"验证errorMessage");

		} catch (Exception e) {
			Logger.fail(e);
		}
	}

	@Test
	@Category(P1.class)
	@TestCase
	public void Tc_BatchValidateRefundV2_002() {
		Logger.start(true, "用户支付后接单前申请效验");
		try {
			// 创建订单
			Logger.comment("前置数据准备");

			TradingServiceResp placeOrderResp = TradingPlaceOrderCallService
					.placeOrderWithTwoProcutInOneOrder(false, false);
			long orderId = placeOrderResp.getOrderList().get(0).getOrderId();
			long tradingId = placeOrderResp.getTradingId();
			long userId = placeOrderResp.getUserId();
			BigDecimal useAccountAmount = placeOrderResp.getPayableAmount();

			TradingCallService.payOrder(userId, useAccountAmount, tradingId);

			Logger.comment("前置数据准备结束");

			// 构造最大可退货退款商品列表
			List<MaxCanRefundAmountVo> maxCanRefundAmountVos = buildMaxCanRefundAmountVoList(placeOrderResp);

			batchValidateRefundReq.setApplyRefundAmount(BigDecimal.ONE);
			batchValidateRefundReq
					.setMaxCanRefundAmountVos(maxCanRefundAmountVos);
			batchValidateRefundReq.setOrderId(orderId);

			batchApplyvalidationCall.setData(batchValidateRefundReq);
			batchApplyvalidationCall.callService();

			Logger.verifyEquals("false",
					batchApplyvalidationCall.getString("success"), "验证返回码");

			Logger.verifyEquals("ERR_CONDITION_NOTMATCH",
					batchApplyvalidationCall.getString("errorCode"), "验证返回码");

			Logger.verifyEquals(String.format("当前订单状态不允许发起退款[%s]", orderId),
					batchApplyvalidationCall.getString("errorMessage"),
					"验证errorMessage");

		} catch (Exception e) {
			Logger.fail(e);
		}
	}

	@Test
	@Category(P1.class)
	@TestCase
	public void Tc_BatchValidateRefundV2_003() {
		Logger.start(true, "商家接单前取消订单,申请效验");
		try {
			// 创建订单
			Logger.comment("前置数据准备");

			TradingServiceResp placeOrderResp = TradingPlaceOrderCallService
					.placeOrderWithTwoProcutInOneOrder(false, false);
			long orderId = placeOrderResp.getOrderList().get(0).getOrderId();
			long tradingId = placeOrderResp.getTradingId();
			long userId = placeOrderResp.getUserId();
			BigDecimal useAccountAmount = placeOrderResp.getPayableAmount();

			TradingCallService.payOrder(userId, useAccountAmount, tradingId);
			TradingCallService.cancelOrder(orderId,
					CancelOrderTypeEnum.BUYER_CANCEL_ORDER, userId);

			Logger.comment("前置数据准备结束");

			List<MaxCanRefundAmountVo> maxCanRefundAmountVos = buildMaxCanRefundAmountVoList(placeOrderResp);

			batchValidateRefundReq.setApplyRefundAmount(BigDecimal.ONE);
			batchValidateRefundReq
					.setMaxCanRefundAmountVos(maxCanRefundAmountVos);
			batchValidateRefundReq.setOrderId(orderId);

			batchApplyvalidationCall.setData(batchValidateRefundReq);
			batchApplyvalidationCall.callService();

			Logger.verifyEquals("false",
					batchApplyvalidationCall.getString("success"), "验证返回码");

			Logger.verifyEquals("ERR_ORDER_CANCELLED",
					batchApplyvalidationCall.getString("errorCode"), "验证返回码");

			Logger.verifyEquals(String.format("订单%s已取消，不能退货退款", orderId),
					batchApplyvalidationCall.getString("errorMessage"),
					"验证errorMessage");

		} catch (Exception e) {
			Logger.fail(e);
		}
	}

	@Test
	@Category(P1.class)
	@TestCase
	public void Tc_BatchValidateRefundV2_004() {
		Logger.start(true, "商家接单后,申请校验");
		try {
			// 创建订单
			Logger.comment("前置数据准备");

			TradingServiceResp placeOrderResp = TradingPlaceOrderCallService
					.placeOrderWithTwoProcutInOneOrder(false, false);
			Order order = placeOrderResp.getOrderList().get(0);
			long orderId = order.getOrderId();
			long tradingId = placeOrderResp.getTradingId();
			long userId = placeOrderResp.getUserId();
			long sellerId = order.getSellerId();
			BigDecimal useAccountAmount = placeOrderResp.getPayableAmount();

			TradingCallService.payOrder(userId, useAccountAmount, tradingId);
			TradingCallService.sellerAcceptOrder(sellerId, orderId);

			Logger.comment("前置数据准备结束");

			List<MaxCanRefundAmountVo> maxCanRefundAmountVos = buildMaxCanRefundAmountVoList(placeOrderResp);

			batchValidateRefundReq.setApplyRefundAmount(BigDecimal.ONE);
			batchValidateRefundReq
					.setMaxCanRefundAmountVos(maxCanRefundAmountVos);
			batchValidateRefundReq.setOrderId(orderId);

			batchApplyvalidationCall.setData(batchValidateRefundReq);
			batchApplyvalidationCall.callService();

			verify(order, order.getOrderDetailPoList(), maxCanRefundAmountVos);

		} catch (Exception e) {

			Logger.fail(e);
		}
	}

	@Test
	@Category(P1.class)
	@TestCase
	public void Tc_BatchValidateRefundV2_005() {
		Logger.start(true, "商家接单后取消订单,申请校验");
		try {
			// 创建订单
			Logger.comment("前置数据准备");

			TradingServiceResp placeOrderResp = TradingPlaceOrderCallService
					.placeOrderWithTwoProcutInOneOrder(false, false);
			Order order = placeOrderResp.getOrderList().get(0);
			long orderId = order.getOrderId();
			long tradingId = placeOrderResp.getTradingId();
			long userId = placeOrderResp.getUserId();
			long sellerId = order.getSellerId();
			BigDecimal useAccountAmount = placeOrderResp.getPayableAmount();

			TradingCallService.payOrder(userId, useAccountAmount, tradingId);
			TradingCallService.sellerAcceptOrder(sellerId, orderId);

			// 取消订单
			TradingCallService.cancelOrder(orderId,
					CancelOrderTypeEnum.CUSTOMER_CANCEL_ORDER, userId);

			Logger.comment("前置数据准备结束");

			List<MaxCanRefundAmountVo> maxCanRefundAmountVos = buildMaxCanRefundAmountVoList(placeOrderResp);

			batchValidateRefundReq.setApplyRefundAmount(BigDecimal.ONE);
			batchValidateRefundReq
					.setMaxCanRefundAmountVos(maxCanRefundAmountVos);
			batchValidateRefundReq.setOrderId(orderId);

			batchApplyvalidationCall.setData(batchValidateRefundReq);
			batchApplyvalidationCall.callService();

			Logger.verifyEquals("false",
					batchApplyvalidationCall.getString("success"), "验证返回码");

			Logger.verifyEquals("ERR_ORDER_CANCELLED",
					batchApplyvalidationCall.getString("errorCode"), "验证返回码");

			Logger.verifyEquals(String.format("订单%s已取消，不能退货退款", orderId),
					batchApplyvalidationCall.getString("errorMessage"),
					"验证errorMessage");

		} catch (Exception e) {
			Logger.fail(e);
		}
	}

	@Test
	@Category(P3.class)
	@TestCase
	public void Tc_BatchValidateRefundV2_006() {
		Logger.start(false, "商品申请退款金额大于(商品可退金额+订单总运费)");
		try {
			// 创建订单
			Logger.comment("前置数据准备");

			TradingServiceResp placeOrderResp = TradingPlaceOrderCallService
					.placeOrderWithTwoProcutInOneOrder(false, false);
			Order order = placeOrderResp.getOrderList().get(0);
			long orderId = order.getOrderId();
			long tradingId = placeOrderResp.getTradingId();
			long userId = placeOrderResp.getUserId();
			long sellerId = order.getSellerId();
			BigDecimal useAccountAmount = placeOrderResp.getPayableAmount();

			TradingCallService.payOrder(userId, useAccountAmount, tradingId);
			TradingCallService.sellerAcceptOrder(sellerId, orderId);

			Logger.comment("前置数据准备结束");

			List<MaxCanRefundAmountVo> maxCanRefundAmountVos = buildMaxCanRefundAmountVoList(placeOrderResp);

			batchValidateRefundReq.setApplyRefundAmount(BigDecimal.ONE);
			batchValidateRefundReq
					.setMaxCanRefundAmountVos(maxCanRefundAmountVos);
			batchValidateRefundReq.setOrderId(orderId);

			batchApplyvalidationCall.setData(batchValidateRefundReq);
			batchApplyvalidationCall.callService();

			verify(order, order.getOrderDetailPoList(), maxCanRefundAmountVos);

		} catch (Exception e) {
			Logger.fail(e);
		}
	}

	@Test
	@Category(P3.class)
	@TestCase
	public void Tc_BatchValidateRefundV2_007() {
		Logger.start(false, "订单退货退款中,申请校验的金额大于最大可退款金额");
		try {
			// 创建订单
			Logger.comment("前置数据准备");

			TradingServiceResp placeOrderResp = TradingPlaceOrderCallService
					.placeOrderWithTwoProcutInOneOrder(false, false);
			Order order = placeOrderResp.getOrderList().get(0);
			long orderId = order.getOrderId();
			long tradingId = placeOrderResp.getTradingId();
			long userId = placeOrderResp.getUserId();
			long sellerId = order.getSellerId();
			BigDecimal useAccountAmount = placeOrderResp.getPayableAmount();

			TradingCallService.payOrder(userId, useAccountAmount, tradingId);
			TradingCallService.sellerAcceptOrder(sellerId, orderId);

			Logger.comment("前置数据准备结束");

			List<MaxCanRefundAmountVo> maxCanRefundAmountVos = buildMaxCanRefundAmountVoList(placeOrderResp);

			batchValidateRefundReq.setApplyRefundAmount(calMaxCanRefundAmount(
					placeOrderResp).add(new BigDecimal(1)));
			batchValidateRefundReq
					.setMaxCanRefundAmountVos(maxCanRefundAmountVos);
			batchValidateRefundReq.setOrderId(orderId);

			batchApplyvalidationCall.setData(batchValidateRefundReq);
			batchApplyvalidationCall.callService();

			Logger.verifyEquals("false",
					batchApplyvalidationCall.getString("success"), "验证返回码");

			Logger.verifyEquals("ErrOrderAmountNotMatch",
					batchApplyvalidationCall.getString("errorCode"), "验证返回码");

			Logger.verifyEquals(String.format("申请退款金额不能大于实际可退款金额", orderId),
					batchApplyvalidationCall.getString("errorMessage"),
					"验证errorMessage");

		} catch (Exception e) {
			Logger.fail(e);
		}
	}

	@Test
	@Category(P1.class)
	@TestCase
	public void Tc_BatchValidateRefundV2_008() {
		Logger.start(true, "用户收货之后申请校验");
		try {
			// 创建订单
			Logger.comment("前置数据准备");

			TradingServiceResp placeOrderResp = TradingPlaceOrderCallService
					.placeOrderWithTwoProcutInOneOrder(false, false);
			Order order = placeOrderResp.getOrderList().get(0);
			long orderId = order.getOrderId();
			long tradingId = placeOrderResp.getTradingId();
			long userId = placeOrderResp.getUserId();
			long sellerId = order.getSellerId();
			BigDecimal useAccountAmount = placeOrderResp.getPayableAmount();

			TradingCallService.payOrder(userId, useAccountAmount, tradingId);
			TradingCallService.sellerAcceptOrder(sellerId, orderId);
			TradingCallService.confirmReceive(userId, orderId);

			Logger.comment("前置数据准备结束");

			List<MaxCanRefundAmountVo> maxCanRefundAmountVos = buildMaxCanRefundAmountVoList(placeOrderResp);

			batchValidateRefundReq.setApplyRefundAmount(BigDecimal.ONE);
			batchValidateRefundReq
					.setMaxCanRefundAmountVos(maxCanRefundAmountVos);
			batchValidateRefundReq.setOrderId(orderId);

			batchApplyvalidationCall.setData(batchValidateRefundReq);
			batchApplyvalidationCall.callService();

			verify(order, order.getOrderDetailPoList(), maxCanRefundAmountVos);

		} catch (Exception e) {
			Logger.fail(e);
		}
	}

	@Test
	@Category(P3.class)
	@TestCase
	public void Tc_BatchValidateRefundV2_009() {
		Logger.start(false, "订单号不存在申请效验");
		try {
			Logger.comment("前置数据准备");

			TradingServiceResp placeOrderResp = TradingPlaceOrderCallService
					.placeOrderWithTwoProcutInOneOrder(false, false);
			Order order = placeOrderResp.getOrderList().get(0);
			long orderId = order.getOrderId();
			long tradingId = placeOrderResp.getTradingId();
			long userId = placeOrderResp.getUserId();
			long sellerId = order.getSellerId();
			BigDecimal useAccountAmount = placeOrderResp.getPayableAmount();

			TradingCallService.payOrder(userId, useAccountAmount, tradingId);
			TradingCallService.sellerAcceptOrder(sellerId, orderId);
			TradingCallService.confirmReceive(userId, orderId);

			Logger.comment("前置数据准备结束");

			List<MaxCanRefundAmountVo> maxCanRefundAmountVos = buildMaxCanRefundAmountVoList(placeOrderResp);

			batchValidateRefundReq.setApplyRefundAmount(BigDecimal.ONE);
			batchValidateRefundReq
					.setMaxCanRefundAmountVos(maxCanRefundAmountVos);
			batchValidateRefundReq.setOrderId(1111111);

			batchApplyvalidationCall.setData(batchValidateRefundReq);
			batchApplyvalidationCall.callService();

			Logger.verifyEquals("false",
					batchApplyvalidationCall.getString("success"), "验证返回码");

			Logger.verifyEquals("ErrOrderNotExists",
					batchApplyvalidationCall.getString("errorCode"), "验证返回码");

			Logger.verifyEquals("订单不存在",
					batchApplyvalidationCall.getString("errorMessage"),
					"验证errorMessage");

		} catch (Exception e) {
			Logger.fail(e);
		}
	}

	@Test
	@Category(P3.class)
	@TestCase
	public void Tc_BatchValidateRefundV2_010() {
		Logger.start(false, "订单号为null申请效验");
		try {
			Logger.comment("前置数据准备");

			TradingServiceResp placeOrderResp = TradingPlaceOrderCallService
					.placeOrderWithTwoProcutInOneOrder(false, false);
			Order order = placeOrderResp.getOrderList().get(0);
			long orderId = order.getOrderId();
			long tradingId = placeOrderResp.getTradingId();
			long userId = placeOrderResp.getUserId();
			long sellerId = order.getSellerId();
			BigDecimal useAccountAmount = placeOrderResp.getPayableAmount();

			TradingCallService.payOrder(userId, useAccountAmount, tradingId);
			TradingCallService.sellerAcceptOrder(sellerId, orderId);
			TradingCallService.confirmReceive(userId, orderId);

			Logger.comment("前置数据准备结束");

			List<MaxCanRefundAmountVo> maxCanRefundAmountVos = buildMaxCanRefundAmountVoList(placeOrderResp);

			batchValidateRefundReq.setApplyRefundAmount(BigDecimal.ONE);
			batchValidateRefundReq
					.setMaxCanRefundAmountVos(maxCanRefundAmountVos);

			batchApplyvalidationCall.setData(batchValidateRefundReq);
			batchApplyvalidationCall.callService();

			Logger.verifyEquals("false",
					batchApplyvalidationCall.getString("success"), "验证返回码");

			Logger.verifyEquals("ILLEGAL_ARGUMENT",
					batchApplyvalidationCall.getString("errorCode"), "验证返回码");

			Logger.verifyEquals("orderId:订单号未提供",
					batchApplyvalidationCall.getString("errorMessage"),
					"验证errorMessage");
		} catch (Exception e) {
			Logger.fail(e);
		}
	}

	@Test
	@Category(P1.class)
	@TestCase
	public void Tc_BatchValidateRefundV2_011() {
		Logger.start(true, "商家发货后,申请退货退款校验");
		try {
			// 创建订单
			Logger.comment("前置数据准备");

			TradingServiceResp placeOrderResp = TradingPlaceOrderCallService
					.placeOrderWithTwoProcutInOneOrder(false, false);
			Order order = placeOrderResp.getOrderList().get(0);
			long orderId = order.getOrderId();
			long tradingId = placeOrderResp.getTradingId();
			long userId = placeOrderResp.getUserId();
			long sellerId = order.getSellerId();
			BigDecimal useAccountAmount = placeOrderResp.getPayableAmount();

			TradingCallService.payOrder(userId, useAccountAmount, tradingId);
			TradingCallService.sellerAcceptOrder(sellerId, orderId);
			TradingCallService.confirmReceive(userId, orderId);
			TradingCallService.delivery(sellerId, orderId, true);

			Logger.comment("前置数据准备结束");

			List<MaxCanRefundAmountVo> maxCanRefundAmountVos = buildMaxCanRefundAmountVoList(placeOrderResp);

			batchValidateRefundReq.setOrderId(orderId);
			batchValidateRefundReq.setApplyRefundAmount(BigDecimal.ONE);
			batchValidateRefundReq
					.setMaxCanRefundAmountVos(maxCanRefundAmountVos);

			batchApplyvalidationCall.setData(batchValidateRefundReq);
			batchApplyvalidationCall.callService();

			verify(order, order.getOrderDetailPoList(), maxCanRefundAmountVos);

		} catch (Exception e) {
			Logger.fail(e);
		}
	}

	@Test
	@Category(P1.class)
	@TestCase
	public void Tc_BatchValidateRefundV2_012() {
		Logger.start(true, "确认收货15天内,申请退货退款校验");
		try {
			// 创建订单
			Logger.comment("前置数据准备");

			TradingServiceResp placeOrderResp = TradingPlaceOrderCallService
					.placeOrderWithTwoProcutInOneOrder(false, false);
			Order order = placeOrderResp.getOrderList().get(0);
			long orderId = order.getOrderId();
			long tradingId = placeOrderResp.getTradingId();
			long userId = placeOrderResp.getUserId();
			long sellerId = order.getSellerId();
			BigDecimal useAccountAmount = placeOrderResp.getPayableAmount();

			TradingCallService.payOrder(userId, useAccountAmount, tradingId);
			TradingCallService.sellerAcceptOrder(sellerId, orderId);
			TradingCallService.confirmReceive(userId, orderId);

			Logger.comment("前置数据准备结束");

			new DefaultWapper().updateOrderConfirmedTimeByOrderId(orderId);

			OrderPo record = new OrderPo();

			Calendar calendar = Calendar.getInstance();
			calendar.setTime(new Date());
			calendar.add(Calendar.DAY_OF_MONTH, -10);
			;

			record.setOrderId(orderId);
			record.setReceiveTime(calendar.getTime());

			orderShardingWapper.orderMapper.updateByPrimaryKeySelective(record);

			Logger.comment("前置数据准备结束");

			List<MaxCanRefundAmountVo> maxCanRefundAmountVos = buildMaxCanRefundAmountVoList(placeOrderResp);

			batchValidateRefundReq.setOrderId(orderId);
			batchValidateRefundReq.setApplyRefundAmount(BigDecimal.ONE);
			batchValidateRefundReq
					.setMaxCanRefundAmountVos(maxCanRefundAmountVos);

			batchApplyvalidationCall.setData(batchValidateRefundReq);
			batchApplyvalidationCall.callService();

			verify(order, order.getOrderDetailPoList(), maxCanRefundAmountVos);

		} catch (Exception e) {
			Logger.fail(e);
		}
	}

	@Test
	@Category(P1.class)
	@TestCase
	public void Tc_BatchValidateRefundV2_013() {
		Logger.start(true, "退货退款中，申请退货退款校验");
		try {

			Logger.comment("前置数据准备");

			TradingServiceResp placeOrderResp = TradingPlaceOrderCallService
					.placeOrderWithTwoProcutInOneOrder(false, false);
			Order order = placeOrderResp.getOrderList().get(0);
			long orderId = order.getOrderId();
			long tradingId = placeOrderResp.getTradingId();
			long userId = placeOrderResp.getUserId();
			long sellerId = order.getSellerId();
			BigDecimal useAccountAmount = placeOrderResp.getPayableAmount();

			TradingCallService.payOrder(userId, useAccountAmount, tradingId);
			TradingCallService.sellerAcceptOrder(sellerId, orderId);
			RefundService.applyRefund(order);

			Logger.comment("前置数据准备结束");

			List<MaxCanRefundAmountVo> maxCanRefundAmountVos = buildMaxCanRefundAmountVoList(placeOrderResp);

			batchValidateRefundReq.setOrderId(orderId);
			batchValidateRefundReq.setApplyRefundAmount(BigDecimal.ONE);
			batchValidateRefundReq
					.setMaxCanRefundAmountVos(maxCanRefundAmountVos);

			batchApplyvalidationCall.setData(batchValidateRefundReq);
			batchApplyvalidationCall.callService();

			Logger.verifyEquals("false",
					batchApplyvalidationCall.getString("success"), "验证返回码");

			Logger.verifyEquals("ErrOrderAmountNotMatch",
					batchApplyvalidationCall.getString("errorCode"), "验证返回码");

			Logger.verifyEquals("申请退款金额不能大于实际可退款金额",
					batchApplyvalidationCall.getString("errorMessage"),
					"验证errorMessage");

		} catch (Exception e) {
			Logger.fail(e);
		}
	}

	@Test
	@Category(P1.class)
	@TestCase
	public void Tc_BatchValidateRefundV2_014() {
		Logger.start(true, "订单商品不是包邮,商品退款加退部分商品运费");
		try {
			Logger.comment("前置数据准备");

			TradingServiceResp placeOrderResp = TradingPlaceOrderCallService
					.placeOrderWithTwoProcutInOneOrder(false, false);
			Order order = placeOrderResp.getOrderList().get(0);
			long orderId = order.getOrderId();
			long tradingId = placeOrderResp.getTradingId();
			long userId = placeOrderResp.getUserId();
			long sellerId = order.getSellerId();
			BigDecimal useAccountAmount = placeOrderResp.getPayableAmount();

			TradingCallService.payOrder(userId, useAccountAmount, tradingId);
			TradingCallService.sellerAcceptOrder(sellerId, orderId);
			TradingCallService.confirmReceive(userId, orderId);

			BigDecimal productTotalFreight = new BigDecimal(0);
			BigDecimal refundAmountExcludeFreight = new BigDecimal(0);

			for (OrderDetailPo orderDetailPo : order.getOrderDetailPoList()) {
				productTotalFreight = productTotalFreight.add(orderDetailPo
						.getFreight());
				refundAmountExcludeFreight = refundAmountExcludeFreight
						.add(orderDetailPo
								.getProductPrice()
								.multiply(
										new BigDecimal(orderDetailPo
												.getProductCount()))
								.subtract(orderDetailPo.getYmtCouponAmount())
								.subtract(orderDetailPo.getSellerCouponAmount()));
			}

			productTotalFreight = productTotalFreight
					.subtract(new BigDecimal(2));
			BigDecimal refundAmount = productTotalFreight
					.add(refundAmountExcludeFreight);

			Logger.comment("前置数据准备结束");

			List<MaxCanRefundAmountVo> maxCanRefundAmountVos = buildMaxCanRefundAmountVoList(placeOrderResp);

			batchValidateRefundReq.setOrderId(orderId);
			batchValidateRefundReq.setApplyRefundAmount(refundAmount);
			batchValidateRefundReq
					.setMaxCanRefundAmountVos(maxCanRefundAmountVos);

			batchApplyvalidationCall.setData(batchValidateRefundReq);
			batchApplyvalidationCall.callService();

			verify(order, order.getOrderDetailPoList(), maxCanRefundAmountVos);

		} catch (Exception e) {
			Logger.fail(e);
		}
	}

	@Test
	@Category(P1.class)
	@TestCase
	public void Tc_BatchValidateRefundV2_015() {
		Logger.start(true, "订单商品不是包邮,商品退款的运费超过商品的运费，但退款总金额不超过订单总运费");
		try {
			// 创建订单
			Logger.comment("前置数据准备");

			TradingServiceResp placeOrderResp = TradingPlaceOrderCallService
					.placeOrderWithTwoProcutInOneOrder(false, false);
			Order order = placeOrderResp.getOrderList().get(0);
			long orderId = order.getOrderId();
			long tradingId = placeOrderResp.getTradingId();
			long userId = placeOrderResp.getUserId();
			long sellerId = order.getSellerId();
			BigDecimal useAccountAmount = placeOrderResp.getPayableAmount();

			TradingCallService.payOrder(userId, useAccountAmount, tradingId);
			TradingCallService.sellerAcceptOrder(sellerId, orderId);
			TradingCallService.confirmReceive(userId, orderId);

			BigDecimal productTotalFreight = new BigDecimal(0);
			BigDecimal refundAmountExcludeFreight = new BigDecimal(0);

			for (OrderDetailPo orderDetailPo : order.getOrderDetailPoList()) {
				productTotalFreight = productTotalFreight.add(orderDetailPo
						.getFreight());
				refundAmountExcludeFreight = refundAmountExcludeFreight
						.add(orderDetailPo
								.getProductPrice()
								.multiply(
										new BigDecimal(orderDetailPo
												.getProductCount()))
								.subtract(orderDetailPo.getYmtCouponAmount())
								.subtract(orderDetailPo.getSellerCouponAmount()));
			}

			productTotalFreight = productTotalFreight.add(new BigDecimal(2));
			BigDecimal refundAmount = productTotalFreight
					.add(refundAmountExcludeFreight.subtract(new BigDecimal(4)));

			Logger.comment("前置数据准备结束");

			List<MaxCanRefundAmountVo> maxCanRefundAmountVos = buildMaxCanRefundAmountVoList(placeOrderResp);

			batchValidateRefundReq.setOrderId(orderId);
			batchValidateRefundReq.setApplyRefundAmount(refundAmount);
			batchValidateRefundReq
					.setMaxCanRefundAmountVos(maxCanRefundAmountVos);

			batchApplyvalidationCall.setData(batchValidateRefundReq);
			batchApplyvalidationCall.callService();

			verify(order, order.getOrderDetailPoList(), maxCanRefundAmountVos);

		} catch (Exception e) {
			Logger.fail(e);
		}
	}

	@Test
	@Category(P1.class)
	@TestCase
	public void Tc_BatchValidateRefundV2_016() {
		Logger.start(true, "退款商品数量大于实际数量");
		try {
			// 创建订单
			Logger.comment("前置数据准备");

			TradingServiceResp placeOrderResp = TradingPlaceOrderCallService
					.placeOrderWithTwoProcutInOneOrder(false, false);
			Order order = placeOrderResp.getOrderList().get(0);
			long orderId = order.getOrderId();
			long tradingId = placeOrderResp.getTradingId();
			long userId = placeOrderResp.getUserId();
			long sellerId = order.getSellerId();
			BigDecimal useAccountAmount = placeOrderResp.getPayableAmount();

			TradingCallService.payOrder(userId, useAccountAmount, tradingId);
			TradingCallService.sellerAcceptOrder(sellerId, orderId);
			TradingCallService.confirmReceive(userId, orderId);

			// 获取第一个商品的商品数量
			int productCount = order.getOrderDetailPoList().get(0)
					.getProductCount();

			Logger.comment("前置数据准备结束");

			List<MaxCanRefundAmountVo> maxCanRefundAmountVos = buildMaxCanRefundAmountVoList(
					placeOrderResp, productCount + 1);

			batchValidateRefundReq.setOrderId(orderId);
			batchValidateRefundReq.setApplyRefundAmount(new BigDecimal(1));
			batchValidateRefundReq
					.setMaxCanRefundAmountVos(maxCanRefundAmountVos);

			batchApplyvalidationCall.setData(batchValidateRefundReq);
			batchApplyvalidationCall.callService();

			Logger.verifyEquals("false",
					batchApplyvalidationCall.getString("success"), "验证返回码");

			Logger.verifyEquals("ERR_CONDITION_NOTMATCH",
					batchApplyvalidationCall.getString("errorCode"), "验证返回码");

			Logger.verifyEquals("申请退商品数量不能大于实际商品数量",
					batchApplyvalidationCall.getString("errorMessage"),
					"验证errorMessage");

		} catch (Exception e) {
			Logger.fail(e);
		}
	}

	@Test
	@Category(P1.class)
	@TestCase
	public void Tc_BatchValidateRefundV2_017() {
		Logger.start(true, "订单商品不是包邮,申请单个商品退款校验");
		try {
			// 创建订单
			Logger.comment("前置数据准备");

			TradingServiceResp placeOrderResp = TradingPlaceOrderCallService
					.placeOrderWithTwoProcutInOneOrder(false, false);
			Order order = placeOrderResp.getOrderList().get(0);
			long orderId = order.getOrderId();
			long tradingId = placeOrderResp.getTradingId();
			long userId = placeOrderResp.getUserId();
			long sellerId = order.getSellerId();
			BigDecimal useAccountAmount = placeOrderResp.getPayableAmount();

			TradingCallService.payOrder(userId, useAccountAmount, tradingId);
			TradingCallService.sellerAcceptOrder(sellerId, orderId);
			TradingCallService.confirmReceive(userId, orderId);

			Logger.comment("前置数据准备结束");

			List<MaxCanRefundAmountVo> maxCanRefundAmountVos = this
					.buildSingleMaxCanRefundAmountVoList(placeOrderResp, 1);

			batchValidateRefundReq.setOrderId(orderId);
			batchValidateRefundReq.setApplyRefundAmount(new BigDecimal(1));
			batchValidateRefundReq
					.setMaxCanRefundAmountVos(maxCanRefundAmountVos);

			batchApplyvalidationCall.setData(batchValidateRefundReq);
			batchApplyvalidationCall.callService();

			verify(order, order.getOrderDetailPoList(), maxCanRefundAmountVos);

		} catch (Exception e) {
			Logger.fail(e);
		}
	}

	@Test
	@Category(P1.class)
	@TestCase
	public void Tc_BatchValidateRefundV2_018() {
		Logger.start(true, "订单商品不是包邮,申请单个商品退款加部分商品运费");
		try {
			// 创建订单
			Logger.comment("前置数据准备");

			TradingServiceResp placeOrderResp = TradingPlaceOrderCallService
					.placeOrderWithTwoProcutInOneOrder(false, false);
			Order order = placeOrderResp.getOrderList().get(0);
			long orderId = order.getOrderId();
			long tradingId = placeOrderResp.getTradingId();
			long userId = placeOrderResp.getUserId();
			long sellerId = order.getSellerId();
			BigDecimal useAccountAmount = placeOrderResp.getPayableAmount();

			TradingCallService.payOrder(userId, useAccountAmount, tradingId);
			TradingCallService.sellerAcceptOrder(sellerId, orderId);
			TradingCallService.confirmReceive(userId, orderId);

			// 第一个订单下的第一个商品
			OrderDetailPo orderInfoPo = order.getOrderDetailPoList().get(0);
			int productNum = orderInfoPo.getProductCount();
			BigDecimal productFreight = orderInfoPo.getFreight();
			BigDecimal refundProductFreight = productFreight
					.subtract(new BigDecimal(2));

			// 计算商品总价格 商品价格 X 数量
			BigDecimal refundAmount = orderInfoPo.getProductPrice()
					.multiply(new BigDecimal(productNum))
					.subtract(orderInfoPo.getYmtCouponAmount())
					.subtract(orderInfoPo.getSellerCouponAmount());

			// 单件商品可退金额
			BigDecimal oneProRefund = refundAmount.divide(new BigDecimal(
					productNum), 2, BigDecimal.ROUND_DOWN);
			Logger.comment("前置数据准备结束");

			List<MaxCanRefundAmountVo> maxCanRefundAmountVos = this
					.buildSingleMaxCanRefundAmountVoList(placeOrderResp, 1);

			batchValidateRefundReq.setOrderId(orderId);
			batchValidateRefundReq.setApplyRefundAmount(oneProRefund
					.add(refundProductFreight));
			batchValidateRefundReq
					.setMaxCanRefundAmountVos(maxCanRefundAmountVos);

			batchApplyvalidationCall.setData(batchValidateRefundReq);
			batchApplyvalidationCall.callService();

			verify(order, order.getOrderDetailPoList(), maxCanRefundAmountVos);

		} catch (Exception e) {
			Logger.fail(e);
		}
	}

	@Test
	@Category(P1.class)
	@TestCase
	public void Tc_BatchValidateRefundV2_019() {
		Logger.start(true, "订单商品不是包邮,申请单个商品退款加上不超过订单总运费");
		try {
			// 创建订单
			Logger.comment("前置数据准备");

			TradingServiceResp placeOrderResp = TradingPlaceOrderCallService
					.placeOrderWithTwoProcutInOneOrder(false, false);
			Order order = placeOrderResp.getOrderList().get(0);
			long orderId = order.getOrderId();
			long tradingId = placeOrderResp.getTradingId();
			long userId = placeOrderResp.getUserId();
			long sellerId = order.getSellerId();
			BigDecimal useAccountAmount = placeOrderResp.getPayableAmount();

			TradingCallService.payOrder(userId, useAccountAmount, tradingId);
			TradingCallService.sellerAcceptOrder(sellerId, orderId);
			TradingCallService.confirmReceive(userId, orderId);

			// 第一个订单下的第一个商品
			OrderDetailPo orderInfoPo = order.getOrderDetailPoList().get(0);
			int productNum = orderInfoPo.getProductCount();
			BigDecimal productFreight = orderInfoPo.getFreight();
			BigDecimal refundProductFreight = productFreight
					.add(new BigDecimal(2));

			// 计算订单总价格 商品价格 X 数量
			BigDecimal refundAmount = orderInfoPo.getProductPrice()
					.multiply(new BigDecimal(productNum))
					.subtract(orderInfoPo.getYmtCouponAmount())
					.subtract(orderInfoPo.getSellerCouponAmount());

			// 单件商品可退金额
			BigDecimal oneProRefund = refundAmount.divide(new BigDecimal(
					productNum), 2, BigDecimal.ROUND_DOWN);

			Logger.comment("前置数据准备结束");

			List<MaxCanRefundAmountVo> maxCanRefundAmountVos = this
					.buildSingleMaxCanRefundAmountVoList(placeOrderResp, 1);

			batchValidateRefundReq.setOrderId(orderId);
			batchValidateRefundReq.setApplyRefundAmount(oneProRefund
					.add(refundProductFreight));
			batchValidateRefundReq
					.setMaxCanRefundAmountVos(maxCanRefundAmountVos);

			batchApplyvalidationCall.setData(batchValidateRefundReq);
			batchApplyvalidationCall.callService();

			verify(order, order.getOrderDetailPoList(), maxCanRefundAmountVos);

		} catch (Exception e) {
			Logger.fail(e);
		}
	}

	@Test
	@Category(P1.class)
	@TestCase
	public void Tc_BatchValidateRefundV2_020() {
		Logger.start(true, "订单商品不是包邮,申请单个商品退款加订单总运费");
		try {
			// 创建订单
			Logger.comment("前置数据准备");

			TradingServiceResp placeOrderResp = TradingPlaceOrderCallService
					.placeOrderWithTwoProcutInOneOrder(false, false);
			Order order = placeOrderResp.getOrderList().get(0);
			long orderId = order.getOrderId();
			long tradingId = placeOrderResp.getTradingId();
			long userId = placeOrderResp.getUserId();
			long sellerId = order.getSellerId();
			BigDecimal useAccountAmount = placeOrderResp.getPayableAmount();

			TradingCallService.payOrder(userId, useAccountAmount, tradingId);
			TradingCallService.sellerAcceptOrder(sellerId, orderId);
			TradingCallService.confirmReceive(userId, orderId);

			// 第一个订单下的第一个商品
			OrderDetailPo orderInfoPo = order.getOrderDetailPoList().get(0);

			int productNum = orderInfoPo.getProductCount();

			// 计算商品总价格 商品价格 X 数量
			BigDecimal refundAmountExcludeFreight = orderInfoPo
					.getProductPrice().multiply(new BigDecimal(productNum))
					.subtract(orderInfoPo.getYmtCouponAmount())
					.subtract(orderInfoPo.getSellerCouponAmount());

			BigDecimal orderFreight = order.getOrderFreight();

			// 单件商品可退金额
			BigDecimal oneProRefund = refundAmountExcludeFreight.divide(
					new BigDecimal(productNum), 2, BigDecimal.ROUND_DOWN);

			Logger.comment("前置数据准备结束");

			List<MaxCanRefundAmountVo> maxCanRefundAmountVos = this
					.buildSingleMaxCanRefundAmountVoList(placeOrderResp, 1);

			batchValidateRefundReq.setOrderId(orderId);
			batchValidateRefundReq.setApplyRefundAmount(oneProRefund
					.add(orderFreight));
			batchValidateRefundReq
					.setMaxCanRefundAmountVos(maxCanRefundAmountVos);

			batchApplyvalidationCall.setData(batchValidateRefundReq);
			batchApplyvalidationCall.callService();

			verify(order, order.getOrderDetailPoList(), maxCanRefundAmountVos);

		} catch (Exception e) {
			Logger.fail(e);
		}
	}

	@Test
	@Category(P1.class)
	@TestCase
	public void Tc_BatchValidateRefundV2_021() {
		Logger.start(true, "订单商品不是包邮,申请单个商品退款加上申请运费超过订单总运费");
		try {
			// 创建订单
			Logger.comment("前置数据准备");

			TradingServiceResp placeOrderResp = TradingPlaceOrderCallService
					.placeOrderWithTwoProcutInOneOrder(false, false);
			Order order = placeOrderResp.getOrderList().get(0);
			long orderId = order.getOrderId();
			long tradingId = placeOrderResp.getTradingId();
			long userId = placeOrderResp.getUserId();
			long sellerId = order.getSellerId();
			BigDecimal useAccountAmount = placeOrderResp.getPayableAmount();

			TradingCallService.payOrder(userId, useAccountAmount, tradingId);
			TradingCallService.sellerAcceptOrder(sellerId, orderId);
			TradingCallService.confirmReceive(userId, orderId);

			// 第一个订单下的第一个商品
			OrderDetailPo orderInfoPo = order.getOrderDetailPoList().get(0);

			int productNum = orderInfoPo.getProductCount();

			// 计算商品总价格 商品价格 X 数量
			BigDecimal refundAmountExcludeFreight = orderInfoPo
					.getProductPrice().multiply(new BigDecimal(productNum))
					.subtract(orderInfoPo.getYmtCouponAmount())
					.subtract(orderInfoPo.getSellerCouponAmount());

			BigDecimal orderFreight = order.getOrderFreight().add(
					new BigDecimal(2));

			// 单件商品可退金额
			BigDecimal oneProRefund = refundAmountExcludeFreight.divide(
					new BigDecimal(productNum), 2, BigDecimal.ROUND_DOWN);

			Logger.comment("前置数据准备结束");

			List<MaxCanRefundAmountVo> maxCanRefundAmountVos = this
					.buildSingleMaxCanRefundAmountVoList(placeOrderResp, 1);

			batchValidateRefundReq.setOrderId(orderId);
			batchValidateRefundReq.setApplyRefundAmount(oneProRefund
					.add(orderFreight));
			batchValidateRefundReq
					.setMaxCanRefundAmountVos(maxCanRefundAmountVos);

			batchApplyvalidationCall.setData(batchValidateRefundReq);
			batchApplyvalidationCall.callService();

			verify(order, order.getOrderDetailPoList(), maxCanRefundAmountVos);

		} catch (Exception e) {
			Logger.fail(e);
		}
	}

	@Test
	@Category(P1.class)
	@TestCase
	public void Tc_BatchValidateRefundV2_022() {
		Logger.start(true, "订单锁定后申请效验");
		try {
			// 创建订单
			Logger.comment("前置数据准备");

			TradingServiceResp placeOrderResp = TradingPlaceOrderCallService
					.placeOrderWithTwoProcutInOneOrder(false, false);
			Order order = placeOrderResp.getOrderList().get(0);
			long orderId = order.getOrderId();
			long tradingId = placeOrderResp.getTradingId();
			long userId = placeOrderResp.getUserId();
			long sellerId = order.getSellerId();
			BigDecimal useAccountAmount = placeOrderResp.getPayableAmount();

			TradingCallService.payOrder(userId, useAccountAmount, tradingId);
			TradingCallService.sellerAcceptOrder(sellerId, orderId);
			TradingCallService.confirmReceive(userId, orderId);

			// 锁定订单
			TradingCallService.markOrderLock(orderId, 1);

			Logger.comment("前置数据准备结束");

			List<MaxCanRefundAmountVo> maxCanRefundAmountVos = buildMaxCanRefundAmountVoList(placeOrderResp);

			batchValidateRefundReq.setApplyRefundAmount(BigDecimal.ONE);
			batchValidateRefundReq
					.setMaxCanRefundAmountVos(maxCanRefundAmountVos);
			batchValidateRefundReq.setOrderId(orderId);

			batchApplyvalidationCall.setData(batchValidateRefundReq);
			batchApplyvalidationCall.callService();

			Logger.verifyEquals("false",
					batchApplyvalidationCall.getString("success"), "验证返回码");

			Logger.verifyEquals("该订单已被客服锁定，暂时无法对该订单进行后续操作",
					batchApplyvalidationCall.getString("errorMessage"),
					"验证errorMessage");

		} catch (Exception e) {
			Logger.fail(e);
		}
	}

	@Test
	@Category(P1.class)
	@TestCase
	public void Tc_BatchValidateRefundV2_023() {
		Logger.start(true, "虚拟商品不能发起退货退款");

		try {
			// 创建订单
			Logger.comment("前置数据准备");

			TradingServiceResp placeOrderResp = TradingPlaceOrderCallService
					.placeOrderWithTwoProcutInOneOrder(false, true);
			Order order = placeOrderResp.getOrderList().get(0);
			long orderId = order.getOrderId();
			long tradingId = placeOrderResp.getTradingId();
			long userId = placeOrderResp.getUserId();
			long sellerId = order.getSellerId();
			BigDecimal useAccountAmount = placeOrderResp.getPayableAmount();

			TradingCallService.payOrder(userId, useAccountAmount, tradingId);
			TradingCallService.sellerAcceptOrder(sellerId, orderId);
			TradingCallService.confirmReceive(userId, orderId);

			Logger.comment("前置数据准备结束");

			List<MaxCanRefundAmountVo> maxCanRefundAmountVos = buildMaxCanRefundAmountVoList(placeOrderResp);

			batchValidateRefundReq.setApplyRefundAmount(BigDecimal.ONE);
			batchValidateRefundReq
					.setMaxCanRefundAmountVos(maxCanRefundAmountVos);
			batchValidateRefundReq.setOrderId(orderId);

			batchApplyvalidationCall.setData(batchValidateRefundReq);
			batchApplyvalidationCall.callService();

			Logger.verifyEquals("false",
					batchApplyvalidationCall.getString("success"), "验证返回码");

			Logger.verifyEquals("ERR_CONDITION_NOTMATCH",
					batchApplyvalidationCall.getString("errorCode"), "验证返回码");

			Logger.verifyEquals(String.format("虚拟商品不能发起退货退款", orderId),
					batchApplyvalidationCall.getString("errorMessage"),
					"验证errorMessage");

		} catch (Exception e) {
			Logger.fail(e);
		}
	}

	@Test
	@Category({ P1.class })
	@TestCase
	public void Tc_BatchValidateRefundV2_024() {
		Logger.start(true, "订单里有包邮非包邮混合商品,退货退款申请校验");
		try {
			// 创建订单
			Logger.comment("前置数据准备");

			TradingServiceResp placeOrderResp = Ts_ApplySalesRefund
					.placeOrder3();
			Order order = placeOrderResp.getOrderList().get(0);
			long sellerId = order.getSellerId();
			long userId = placeOrderResp.getUserId();
			long tradingId = placeOrderResp.getTradingId();
			long orderId = order.getOrderId();
			BigDecimal amount = placeOrderResp.getPayableAmount();

			TradingCallService.payOrder(userId, amount, tradingId);
			TradingCallService.sellerAcceptOrder(sellerId, orderId);

			Logger.comment("前置数据准备结束");

			List<MaxCanRefundAmountVo> maxCanRefundAmountVos = buildMaxCanRefundAmountVoList(placeOrderResp);

			batchValidateRefundReq.setApplyRefundAmount(BigDecimal.ONE);
			batchValidateRefundReq
					.setMaxCanRefundAmountVos(maxCanRefundAmountVos);
			batchValidateRefundReq.setOrderId(orderId);

			batchApplyvalidationCall.setData(batchValidateRefundReq);
			batchApplyvalidationCall.callService();

			verify(order, order.getOrderDetailPoList(), maxCanRefundAmountVos);

		} catch (Exception e) {
			Logger.fail(e);
		}
	}

	@Test
	@Category({ P1.class })
	@TestCase
	public void Tc_BatchValidateRefundV2_025() {
		Logger.start(true, "订单里有包邮非包邮混合商品,非包邮商品退货退款申请校验");
		try {
			// 创建订单
			Logger.comment("前置数据准备");

			TradingServiceResp placeOrderResp = Ts_ApplySalesRefund
					.placeOrder3();
			Order order = placeOrderResp.getOrderList().get(0);
			long sellerId = order.getSellerId();
			long userId = placeOrderResp.getUserId();
			long tradingId = placeOrderResp.getTradingId();
			long orderId = order.getOrderId();
			BigDecimal amount = placeOrderResp.getPayableAmount();

			TradingCallService.payOrder(userId, amount, tradingId);
			TradingCallService.sellerAcceptOrder(sellerId, orderId);

			// 第二个商品为无运费商品
			OrderDetailPo orderDetailPo = order.getOrderDetailPoList().get(1);
			int productNum = orderDetailPo.getProductCount();

			// 计算订单总价格 商品价格 X 数量
			BigDecimal refundAmount = orderDetailPo.getProductPrice()
					.multiply(new BigDecimal(productNum))
					.subtract(orderDetailPo.getYmtCouponAmount())
					.subtract(orderDetailPo.getSellerCouponAmount());
			Logger.comment("前置数据准备结束");

			List<MaxCanRefundAmountVo> maxCanRefundAmountVos = new ArrayList<MaxCanRefundAmountVo>();

			MaxCanRefundAmountVo vo = new MaxCanRefundAmountVo();
			vo.setCatalogId(orderDetailPo.getCatalogId());
			vo.setApplyRefundCount(orderDetailPo.getProductCount());
			vo.setMaxCanRefundAmount(getOrderDetailPaidAmountExcludeFreight(
					orderDetailPo, orderDetailPo.getProductCount()));
			vo.setMaxCanRefundFreight(orderDetailPo.getFreight());

			maxCanRefundAmountVos.add(vo);

			batchValidateRefundReq.setApplyRefundAmount(refundAmount
					.add(BigDecimal.ONE));
			batchValidateRefundReq
					.setMaxCanRefundAmountVos(maxCanRefundAmountVos);
			batchValidateRefundReq.setOrderId(orderId);

			batchApplyvalidationCall.setData(batchValidateRefundReq);
			batchApplyvalidationCall.callService();

			verify(order, order.getOrderDetailPoList(), maxCanRefundAmountVos,
					false);

		} catch (Exception e) {
			Logger.fail(e);
		}
	}

	@Test
	@Category(P1.class)
	@TestCase
	public void Tc_BatchValidateRefundV2_026() {
		Logger.start(true, "订单商品不是包邮,申请单个商品退款金额大于可退款总金额");
		try {
			// 创建订单
			Logger.comment("前置数据准备");

			TradingServiceResp placeOrderResp = TradingPlaceOrderCallService
					.placeOrderWithTwoProcutInOneOrder(false, false);
			Order order = placeOrderResp.getOrderList().get(0);
			long orderId = order.getOrderId();
			long tradingId = placeOrderResp.getTradingId();
			long userId = placeOrderResp.getUserId();
			long sellerId = order.getSellerId();
			BigDecimal useAccountAmount = placeOrderResp.getPayableAmount();

			TradingCallService.payOrder(userId, useAccountAmount, tradingId);
			TradingCallService.sellerAcceptOrder(sellerId, orderId);
			TradingCallService.confirmReceive(userId, orderId);

			BigDecimal totalRefundAmount = this
					.calMaxCanRefundAmount(placeOrderResp);
			Logger.comment("前置数据准备结束");

			List<MaxCanRefundAmountVo> maxCanRefundAmountVos = this
					.buildSingleMaxCanRefundAmountVoList(placeOrderResp, 1);

			batchValidateRefundReq.setOrderId(orderId);
			batchValidateRefundReq.setApplyRefundAmount(totalRefundAmount
					.add(BigDecimal.ONE));
			batchValidateRefundReq
					.setMaxCanRefundAmountVos(maxCanRefundAmountVos);

			batchApplyvalidationCall.setData(batchValidateRefundReq);
			batchApplyvalidationCall.callService();

			Logger.verifyEquals("false",
					batchApplyvalidationCall.getString("success"), "验证返回码");

			Logger.verifyEquals("ErrOrderAmountNotMatch",
					batchApplyvalidationCall.getString("errorCode"), "验证返回码");

			Logger.verifyEquals("申请退款金额不能大于实际可退款金额",
					batchApplyvalidationCall.getString("errorMessage"),
					"验证errorMessage");

		} catch (Exception e) {
			Logger.fail(e);
		}
	}

	@Test
	@Category({ P1.class })
	@TestCase
	public void Tc_BatchValidateRefundV2_027() {
		Logger.start(true, "订单里有包邮非包邮混合商品,非包邮商品退货退款申请退款金额大于可退款总金额");
		try {
			// 创建订单
			Logger.comment("前置数据准备");

			TradingServiceResp placeOrderResp = Ts_ApplySalesRefund
					.placeOrder3();
			Order order = placeOrderResp.getOrderList().get(0);
			long sellerId = order.getSellerId();
			long userId = placeOrderResp.getUserId();
			long tradingId = placeOrderResp.getTradingId();
			long orderId = order.getOrderId();
			BigDecimal amount = placeOrderResp.getPayableAmount();

			TradingCallService.payOrder(userId, amount, tradingId);
			TradingCallService.sellerAcceptOrder(sellerId, orderId);

			BigDecimal totalRefundAmount = this
					.calMaxCanRefundAmount(placeOrderResp);
			// 第二个商品为无运费商品
			OrderDetailPo orderDetailPo = order.getOrderDetailPoList().get(1);

			Logger.comment("前置数据准备结束");

			List<MaxCanRefundAmountVo> maxCanRefundAmountVos = new ArrayList<MaxCanRefundAmountVo>();

			MaxCanRefundAmountVo vo = new MaxCanRefundAmountVo();
			vo.setCatalogId(orderDetailPo.getCatalogId());
			vo.setApplyRefundCount(orderDetailPo.getProductCount());
			vo.setMaxCanRefundAmount(getOrderDetailPaidAmountExcludeFreight(
					orderDetailPo, orderDetailPo.getProductCount()));
			vo.setMaxCanRefundFreight(orderDetailPo.getFreight());

			maxCanRefundAmountVos.add(vo);

			batchValidateRefundReq.setApplyRefundAmount(totalRefundAmount
					.add(BigDecimal.ONE));
			batchValidateRefundReq
					.setMaxCanRefundAmountVos(maxCanRefundAmountVos);
			batchValidateRefundReq.setOrderId(orderId);

			batchApplyvalidationCall.setData(batchValidateRefundReq);
			batchApplyvalidationCall.callService();

			Logger.verifyEquals("false",
					batchApplyvalidationCall.getString("success"), "验证返回码");

			Logger.verifyEquals("ErrOrderAmountNotMatch",
					batchApplyvalidationCall.getString("errorCode"), "验证返回码");

			Logger.verifyEquals("申请退款金额不能大于实际可退款金额",
					batchApplyvalidationCall.getString("errorMessage"),
					"验证errorMessage");

		} catch (Exception e) {
			Logger.fail(e);
		}
	}

	@Test
	@Category(P1.class)
	@TestCase
	public void Tc_BatchValidateRefundV2_028() {
		Logger.start(true, "申请退款金额为0");
		try {
			// 创建订单
			Logger.comment("前置数据准备");

			TradingServiceResp placeOrderResp = TradingPlaceOrderCallService
					.placeOrderWithTwoProcutInOneOrder(false, false);
			Order order = placeOrderResp.getOrderList().get(0);
			long orderId = order.getOrderId();
			long tradingId = placeOrderResp.getTradingId();
			long userId = placeOrderResp.getUserId();
			long sellerId = order.getSellerId();
			BigDecimal useAccountAmount = placeOrderResp.getPayableAmount();

			TradingCallService.payOrder(userId, useAccountAmount, tradingId);
			TradingCallService.sellerAcceptOrder(sellerId, orderId);
			TradingCallService.confirmReceive(userId, orderId);

			// 获取第一个商品的商品数量
			int productCount = order.getOrderDetailPoList().get(0)
					.getProductCount();

			Logger.comment("前置数据准备结束");

			List<MaxCanRefundAmountVo> maxCanRefundAmountVos = buildMaxCanRefundAmountVoList(
					placeOrderResp, productCount + 1);

			batchValidateRefundReq.setOrderId(orderId);
			batchValidateRefundReq.setApplyRefundAmount(new BigDecimal(0));
			batchValidateRefundReq
					.setMaxCanRefundAmountVos(maxCanRefundAmountVos);

			batchApplyvalidationCall.setData(batchValidateRefundReq);
			batchApplyvalidationCall.callService();

			Logger.verifyEquals("false",
					batchApplyvalidationCall.getString("success"), "验证返回码");

			Logger.verifyEquals("ILLEGAL_ARGUMENT",
					batchApplyvalidationCall.getString("errorCode"), "验证返回码");

			Logger.verifyEquals(
					"applyRefundAmount:must be greater than or equal to 0.01",
					batchApplyvalidationCall.getString("errorMessage"),
					"验证errorMessage");

		} catch (Exception e) {
			Logger.fail(e);
		}
	}

	@Test
	@Category(P1.class)
	@TestCase
	public void Tc_BatchValidateRefundV2_029() {
		Logger.start(true,
				"一个订单两个买家商品，买家承担鉴定费和鉴定物流费, 部分退货退款，申请退款金额小于商品可退鉴别费金额，校验成功");
		try {
			// 创建订单
			Logger.comment("前置数据准备");

			TradingServiceResp placeOrderResp = TradingPlaceAuthenticateCallService
					.placeOrderWithAuthenticateWithTwoProduct(
							AuthenticateFreightTypeEnum.BUYER, BigDecimal.ONE,
							AuthenticateFeeTypeEnum.BUYER, BigDecimal.TEN);

			Order order = placeOrderResp.getOrderList().get(0);

			long orderId = order.getOrderId();
			long tradingId = placeOrderResp.getTradingId();
			long userId = placeOrderResp.getUserId();
			long sellerId = order.getSellerId();

			BigDecimal useAccountAmount = placeOrderResp.getPayableAmount();

			TradingCallService.payOrder(userId, useAccountAmount, tradingId);
			TradingCallService.sellerAcceptOrder(sellerId, orderId);

			// 获取第一个商品的商品数量
			int productCount = order.getOrderDetailPoList().get(0)
					.getProductCount();

			Logger.comment("前置数据准备结束");

			List<MaxCanRefundAmountVo> maxCanRefundAmountVos = buildMaxCanRefundAmountVoList(
					placeOrderResp, productCount);

			batchValidateRefundReq.setOrderId(orderId);
			batchValidateRefundReq.setApplyRefundAmount(BigDecimal.ONE);
			batchValidateRefundReq
					.setMaxCanRefundAmountVos(maxCanRefundAmountVos);

			batchApplyvalidationCall.setData(batchValidateRefundReq);
			batchApplyvalidationCall.callService();

			verify(order, order.getOrderDetailPoList(), maxCanRefundAmountVos);

		} catch (Exception e) {
			Logger.fail(e);
		}
	}

	@Test
	@Category(P1.class)
	@TestCase
	public void Tc_BatchValidateRefundV2_030() {
		Logger.start(true,
				"一个订单两个买家商品，买家承担鉴定费和鉴定物流费, 全部退货退款，申请退款金额等于商品支付金额，校验成功");
		try {
			// 创建订单
			Logger.comment("前置数据准备");

			TradingServiceResp placeOrderResp = TradingPlaceAuthenticateCallService
					.placeOrderWithAuthenticateWithTwoProduct(
							AuthenticateFreightTypeEnum.BUYER, BigDecimal.ONE,
							AuthenticateFeeTypeEnum.BUYER, BigDecimal.TEN);

			Order order = placeOrderResp.getOrderList().get(0);

			long orderId = order.getOrderId();
			long tradingId = placeOrderResp.getTradingId();
			long userId = placeOrderResp.getUserId();
			long sellerId = order.getSellerId();

			BigDecimal useAccountAmount = placeOrderResp.getPayableAmount();

			TradingCallService.payOrder(userId, useAccountAmount, tradingId);
			TradingCallService.sellerAcceptOrder(sellerId, orderId);

			// 获取第一个商品的商品数量
			int productCount = order.getOrderDetailPoList().get(0)
					.getProductCount();

			Logger.comment("前置数据准备结束");

			List<MaxCanRefundAmountVo> maxCanRefundAmountVos = buildMaxCanRefundAmountVoList(
					placeOrderResp, productCount);

			BigDecimal totalRefundAmount = maxCanRefundAmountVos
					.stream()
					.map(maxCanRefundAmountVo -> maxCanRefundAmountVo
							.getMaxCanRefundAmount().add(
									maxCanRefundAmountVo
											.getMaxCanRefundFreight()))
					.reduce(BigDecimal.ZERO, BigDecimal::add);

			batchValidateRefundReq.setOrderId(orderId);
			batchValidateRefundReq.setApplyRefundAmount(totalRefundAmount);
			batchValidateRefundReq
					.setMaxCanRefundAmountVos(maxCanRefundAmountVos);

			batchApplyvalidationCall.setData(batchValidateRefundReq);
			batchApplyvalidationCall.callService();

			verify(order, order.getOrderDetailPoList(), maxCanRefundAmountVos);

		} catch (Exception e) {
			Logger.fail(e);
		}
	}

	@Test
	@Category(P1.class)
	@TestCase
	@Ignore
	public void Tc_BatchValidateRefundV2_031() {
		Logger.start(true,
				"买家承担鉴定费和鉴定物流费，订单商品一个一个退，直到商品全部退完，申请退款金额等于商品支付金额，校验成功");
		try {
			// 创建订单
			Logger.comment("前置数据准备");

			TradingServiceResp placeOrderResp = TradingPlaceAuthenticateCallService
					.placeOrderWithAuthenticate(
							AuthenticateFreightTypeEnum.BUYER, BigDecimal.ONE,
							AuthenticateFeeTypeEnum.BUYER, BigDecimal.TEN);

			Order order = placeOrderResp.getOrderList().get(0);

			long orderId = order.getOrderId();
			long tradingId = placeOrderResp.getTradingId();
			long userId = placeOrderResp.getUserId();
			long sellerId = order.getSellerId();

			BigDecimal useAccountAmount = placeOrderResp.getPayableAmount();

			TradingCallService.payOrder(userId, useAccountAmount, tradingId);
			TradingCallService.sellerAcceptOrder(sellerId, orderId);

			Logger.comment("前置数据准备结束");

			List<MaxCanRefundAmountVo> maxCanRefundAmountVos = this
					.buildSingleOneByOneMaxCanRefundAmountVoList(placeOrderResp, 0);

			BigDecimal totalRefundAmount = maxCanRefundAmountVos
					.stream()
					.map(maxCanRefundAmountVo -> maxCanRefundAmountVo
							.getMaxCanRefundAmount().add(
									maxCanRefundAmountVo
											.getMaxCanRefundFreight()))
					.reduce(BigDecimal.ZERO, BigDecimal::add);

			batchValidateRefundReq.setOrderId(orderId);
			batchValidateRefundReq.setApplyRefundAmount(totalRefundAmount);
			batchValidateRefundReq
					.setMaxCanRefundAmountVos(maxCanRefundAmountVos);

			batchApplyvalidationCall.setData(batchValidateRefundReq);
			batchApplyvalidationCall.callService();

			verify(order, order.getOrderDetailPoList(), maxCanRefundAmountVos);

		} catch (Exception e) {
			Logger.fail(e);
		}
	}
	
	@Test
	@Category(P1.class)
	@TestCase
	@Ignore
	public void Tc_BatchValidateRefundV2_032() {
		Logger.start(true,
				"买家承担鉴定费和鉴定物流费，先退一个商品，剩下的商品一个一个退，直到商品全部退完，申请退款金额等于剩下商品的可退总额，校验成功");
		try {
			// 创建订单
			Logger.comment("前置数据准备");

			TradingServiceResp placeOrderResp = TradingPlaceAuthenticateCallService
					.placeOrderWithAuthenticate(
							AuthenticateFreightTypeEnum.BUYER, BigDecimal.ONE,
							AuthenticateFeeTypeEnum.BUYER, BigDecimal.TEN);

			Order order = placeOrderResp.getOrderList().get(0);

			long orderId = order.getOrderId();
			long tradingId = placeOrderResp.getTradingId();
			long userId = placeOrderResp.getUserId();
			long sellerId = order.getSellerId();

			BigDecimal useAccountAmount = placeOrderResp.getPayableAmount();

			TradingCallService.payOrder(userId, useAccountAmount, tradingId);
			TradingCallService.sellerAcceptOrder(sellerId, orderId);
			
			// 先退一个商品
			RefundService.buildSingleApplyRefundReq(orderId, order
					.getOrderDetailPoList().get(0), BigDecimal.ZERO, 1);

			Logger.comment("前置数据准备结束");

			List<MaxCanRefundAmountVo> maxCanRefundAmountVos = this
					.buildSingleOneByOneMaxCanRefundAmountVoList(placeOrderResp, 1);

			BigDecimal totalRefundAmount = maxCanRefundAmountVos
					.stream()
					.map(maxCanRefundAmountVo -> maxCanRefundAmountVo
							.getMaxCanRefundAmount().add(
									maxCanRefundAmountVo
											.getMaxCanRefundFreight()))
					.reduce(BigDecimal.ZERO, BigDecimal::add);

			batchValidateRefundReq.setOrderId(orderId);
			batchValidateRefundReq.setApplyRefundAmount(totalRefundAmount);
			batchValidateRefundReq
					.setMaxCanRefundAmountVos(maxCanRefundAmountVos);

			batchApplyvalidationCall.setData(batchValidateRefundReq);
			batchApplyvalidationCall.callService();

			verify(order, order.getOrderDetailPoList(), maxCanRefundAmountVos);

		} catch (Exception e) {
			Logger.fail(e);
		}
	}

	@Test
	@Category(P1.class)
	@TestCase
	public void Tc_BatchValidateRefundV2_033() {
		Logger.start(true,
				"一个订单两个买家商品，买家承担鉴定费和鉴定物流费，全部退货退款，申请退款金额=买家商品鉴别费+买家鉴别运费，校验成功");
		try {
			// 创建订单
			Logger.comment("前置数据准备");

			TradingServiceResp placeOrderResp = TradingPlaceAuthenticateCallService
					.placeOrderWithAuthenticateWithTwoProduct(
							AuthenticateFreightTypeEnum.BUYER, BigDecimal.ONE,
							AuthenticateFeeTypeEnum.BUYER, BigDecimal.TEN);

			Order order = placeOrderResp.getOrderList().get(0);

			long orderId = order.getOrderId();
			long tradingId = placeOrderResp.getTradingId();
			long userId = placeOrderResp.getUserId();
			long sellerId = order.getSellerId();

			BigDecimal useAccountAmount = placeOrderResp.getPayableAmount();

			TradingCallService.payOrder(userId, useAccountAmount, tradingId);
			TradingCallService.sellerAcceptOrder(sellerId, orderId);

			// 获取第一个商品的商品数量
			int productCount = order.getOrderDetailPoList().get(0)
					.getProductCount();

			Logger.comment("前置数据准备结束");

			List<MaxCanRefundAmountVo> maxCanRefundAmountVos = buildMaxCanRefundAmountVoList(
					placeOrderResp, productCount);

			BigDecimal totalRefundAmount = order
					.getOrderDetailPoList()
					.stream()
					.map(orderDetailPo -> orderDetailPo.getAuthenticateFee()
							.multiply(
									new BigDecimal(orderDetailPo
											.getProductCount())))
					.reduce(BigDecimal.ZERO, BigDecimal::add)
					.add(order.getUserAuthenticateFreightFee());

			batchValidateRefundReq.setOrderId(orderId);
			batchValidateRefundReq.setApplyRefundAmount(totalRefundAmount);
			batchValidateRefundReq
					.setMaxCanRefundAmountVos(maxCanRefundAmountVos);

			batchApplyvalidationCall.setData(batchValidateRefundReq);
			batchApplyvalidationCall.callService();

			verify(order, order.getOrderDetailPoList(), maxCanRefundAmountVos);

		} catch (Exception e) {
			Logger.fail(e);
		}
	}
	
	@Test
	@Category(P1.class)
	@TestCase
	public void Tc_BatchValidateRefundV2_034() {
		Logger.start(true,
				"一个订单两个商品，买家承担鉴定费和买手物流费，全部退货退款，申请退款金额=支付金额+买手鉴别运费，校验失败");
		try {
			// 创建订单
			Logger.comment("前置数据准备");

			TradingServiceResp placeOrderResp = TradingPlaceAuthenticateCallService
					.placeOrderWithAuthenticateWithTwoProduct(
							AuthenticateFreightTypeEnum.SELLER, BigDecimal.ONE,
							AuthenticateFeeTypeEnum.BUYER, BigDecimal.TEN);

			Order order = placeOrderResp.getOrderList().get(0);

			long orderId = order.getOrderId();
			long tradingId = placeOrderResp.getTradingId();
			long userId = placeOrderResp.getUserId();
			long sellerId = order.getSellerId();

			BigDecimal useAccountAmount = placeOrderResp.getPayableAmount();

			TradingCallService.payOrder(userId, useAccountAmount, tradingId);
			TradingCallService.sellerAcceptOrder(sellerId, orderId);

			// 获取第一个商品的商品数量
			int productCount = order.getOrderDetailPoList().get(0)
					.getProductCount();

			Logger.comment("前置数据准备结束");

			List<MaxCanRefundAmountVo> maxCanRefundAmountVos = buildMaxCanRefundAmountVoList(
					placeOrderResp, productCount);

			BigDecimal totalRefundAmount = maxCanRefundAmountVos
					.stream()
					.map(maxCanRefundAmountVo -> maxCanRefundAmountVo
							.getMaxCanRefundAmount().add(
									maxCanRefundAmountVo
											.getMaxCanRefundFreight()))
					.reduce(BigDecimal.ZERO, BigDecimal::add).add(BigDecimal.ONE);

			batchValidateRefundReq.setOrderId(orderId);
			batchValidateRefundReq.setApplyRefundAmount(totalRefundAmount);
			batchValidateRefundReq
					.setMaxCanRefundAmountVos(maxCanRefundAmountVos);

			batchApplyvalidationCall.setData(batchValidateRefundReq);
			batchApplyvalidationCall.callService();

			Logger.verifyEquals("false",
					batchApplyvalidationCall.getString("success"), "验证返回码");

			Logger.verifyEquals("ErrOrderAmountNotMatch",
					batchApplyvalidationCall.getString("errorCode"), "验证返回码");

			Logger.verifyEquals(
					"申请退款金额不能大于实际可退款金额",
					batchApplyvalidationCall.getString("errorMessage"),
					"验证errorMessage");

		} catch (Exception e) {
			Logger.fail(e);
		}
	}
	
	@Test
	@Category(P1.class)
	@TestCase
	public void Tc_BatchValidateRefundV2_035() {
		Logger.start(true,
				"一个订单两个买家商品，买家承担鉴定费和鉴定物流费, 鉴定中心发货，全部退货退款，申请退款金额等于商品支付金额，校验成功");
		try {
			// 创建订单
			Logger.comment("前置数据准备");

			TradingServiceResp placeOrderResp = TradingPlaceAuthenticateCallService
					.placeOrderWithAuthenticateWithTwoProduct(
							AuthenticateFreightTypeEnum.BUYER, BigDecimal.ONE,
							AuthenticateFeeTypeEnum.BUYER, BigDecimal.TEN);

			Order order = placeOrderResp.getOrderList().get(0);

			long orderId = order.getOrderId();
			long tradingId = placeOrderResp.getTradingId();
			long userId = placeOrderResp.getUserId();
			long sellerId = order.getSellerId();

			BigDecimal useAccountAmount = placeOrderResp.getPayableAmount();

			TradingCallService.payOrder(userId, useAccountAmount, tradingId);
			TradingCallService.sellerAcceptOrder(sellerId, orderId);
			Thread.sleep(3000);
			
			// 国际段发货
			TradingCallService.delivery(sellerId, orderId, LogisticsTypeEnum.OVERSEAS_DELIVERY, "Y013", 1, true);
			
			// 鉴定中心发货
			TradingCallService.authenticateDelivery(sellerId, orderId);

			// 获取第一个商品的商品数量
			int productCount = order.getOrderDetailPoList().get(0)
					.getProductCount();

			Logger.comment("前置数据准备结束");

			List<MaxCanRefundAmountVo> maxCanRefundAmountVos = buildMaxCanRefundAmountVoList(
					placeOrderResp, productCount);

			BigDecimal totalRefundAmount = maxCanRefundAmountVos
					.stream()
					.map(maxCanRefundAmountVo -> maxCanRefundAmountVo
							.getMaxCanRefundAmount().add(
									maxCanRefundAmountVo
											.getMaxCanRefundFreight()))
					.reduce(BigDecimal.ZERO, BigDecimal::add);

			batchValidateRefundReq.setOrderId(orderId);
			batchValidateRefundReq.setApplyRefundAmount(totalRefundAmount);
			batchValidateRefundReq
					.setMaxCanRefundAmountVos(maxCanRefundAmountVos);

			batchApplyvalidationCall.setData(batchValidateRefundReq);
			batchApplyvalidationCall.callService();

			verify(order, order.getOrderDetailPoList(), maxCanRefundAmountVos);

		} catch (Exception e) {
			Logger.fail(e);
		}
	}
	
	@Test
	@Category(P1.class)
	@TestCase
	public void Tc_BatchValidateRefundV2_036() {
		Logger.start(true,
				"一个订单包含一个买家鉴定费商品，一个普通商品, 买家鉴定费商品全部退货退款，申请退款金额等于商品支付金额，校验成功");
		try {
			// 创建订单
			Logger.comment("前置数据准备");

			TradingServiceResp placeOrderResp = TradingPlaceAuthenticateCallService
					.placeOrderWithAuthenticateWithTwoTypeProduct(
							AuthenticateFreightTypeEnum.BUYER, BigDecimal.ONE,
							AuthenticateFeeTypeEnum.BUYER, BigDecimal.TEN);

			Order order = placeOrderResp.getOrderList().get(0);

			long orderId = order.getOrderId();
			long tradingId = placeOrderResp.getTradingId();
			long userId = placeOrderResp.getUserId();
			long sellerId = order.getSellerId();

			BigDecimal useAccountAmount = placeOrderResp.getPayableAmount();

			TradingCallService.payOrder(userId, useAccountAmount, tradingId);
			TradingCallService.sellerAcceptOrder(sellerId, orderId);
			Thread.sleep(3000);
			
			// 国际段发货
			TradingCallService.delivery(sellerId, orderId, LogisticsTypeEnum.OVERSEAS_DELIVERY, "Y013", 1, true);
			
			// 获取第一个商品的商品数量
			OrderDetailPo orderDetailPo = order.getOrderDetailPoList().stream()
					.filter(od -> od.getAuthenticateFlag() == true)
					.collect(Collectors.toList()).get(0);

			Logger.comment("前置数据准备结束");

			List<MaxCanRefundAmountVo> maxCanRefundAmountVos = buildSingleMaxCanRefundAmountVoList(orderDetailPo, 0);

			maxCanRefundAmountVos.stream().forEach(
					maxCanRefundAmountVo -> {
						maxCanRefundAmountVo
								.setMaxCanRefundAuthenticateFee(order
										.getUserAuthenticateFee(orderDetailPo
												.getProductCount()).add(order.getUserAuthenticateFreightFee()));
					});
			BigDecimal totalRefundAmount = maxCanRefundAmountVos
					.stream()
					.map(maxCanRefundAmountVo -> maxCanRefundAmountVo
							.getMaxCanRefundAmount()
							.add(maxCanRefundAmountVo.getMaxCanRefundFreight())
							.add(maxCanRefundAmountVo
									.getMaxCanRefundAuthenticateFee()))
					.reduce(BigDecimal.ZERO, BigDecimal::add);

			batchValidateRefundReq.setOrderId(orderId);
			batchValidateRefundReq.setApplyRefundAmount(totalRefundAmount.add(
					order.getUserAuthenticateFee(orderDetailPo
							.getProductCount())).add(
					order.getUserAuthenticateFreightFee()));
			batchValidateRefundReq
					.setMaxCanRefundAmountVos(maxCanRefundAmountVos);

			batchApplyvalidationCall.setData(batchValidateRefundReq);
			batchApplyvalidationCall.callService();

			verify(order, order.getOrderDetailPoList(), maxCanRefundAmountVos);

		} catch (Exception e) {
			Logger.fail(e);
		}
	}
	
	public BigDecimal calMaxCanRefundAmount(TradingServiceResp placeOrderResp) {

		Order order = placeOrderResp.getOrderList().get(0);
		BigDecimal refundAmount = new BigDecimal(0);

		for (OrderDetailPo orderDetailPo : order.getOrderDetailPoList()) {
			refundAmount = refundAmount
					.add(orderDetailPo.getProductPrice().multiply(
							new BigDecimal(orderDetailPo.getProductCount())))
					.subtract(orderDetailPo.getSellerCouponAmount())
					.subtract(orderDetailPo.getYmtCouponAmount())
					.subtract(orderDetailPo.getYmtPromotionAmount())
					.subtract(
							Utils.zeroIfNull(orderDetailPo
									.getThirdpartyDiscount()))
					.add(orderDetailPo.getFreight())
					.add(RefundService.getUserAuthenticateFee(orderDetailPo,
							orderDetailPo.getProductCount()));
		}

		return refundAmount.add(placeOrderResp.getOrderList().get(0)
				.getUserAuthenticateFreightFee());
	}

	public List<MaxCanRefundAmountVo> buildMaxCanRefundAmountVoList(
			TradingServiceResp placeOrderResp) {
		return buildMaxCanRefundAmountVoList(placeOrderResp, 0);
	}

	public List<MaxCanRefundAmountVo> buildSingleMaxCanRefundAmountVoList(
			TradingServiceResp placeOrderResp) {
		return buildSingleMaxCanRefundAmountVoList(placeOrderResp, 0);
	}

	public List<MaxCanRefundAmountVo> buildSingleMaxCanRefundAmountVoList(
			TradingServiceResp placeOrderResp, int productNum) {
		List<MaxCanRefundAmountVo> maxCanRefundAmountVos = new ArrayList<MaxCanRefundAmountVo>();

		MaxCanRefundAmountVo vo1 = new MaxCanRefundAmountVo();
		vo1.setCatalogId(placeOrderResp.getOrderList().get(0)
				.getOrderDetailPoList().get(0).getCatalogId());

		if (productNum != 0)
			vo1.setApplyRefundCount(productNum);
		else
			vo1.setApplyRefundCount(placeOrderResp.getOrderList().get(0)
					.getOrderDetailPoList().get(0).getProductCount());

		vo1.setMaxCanRefundAmount(getOrderDetailPaidAmountExcludeFreight(
				placeOrderResp.getOrderList().get(0).getOrderDetailPoList()
						.get(0), placeOrderResp.getOrderList().get(0)
						.getOrderDetailPoList().get(0).getProductCount()));
		vo1.setMaxCanRefundFreight(placeOrderResp.getOrderList().get(0)
				.getOrderDetailPoList().get(0).getFreight());

		maxCanRefundAmountVos.add(vo1);

		return maxCanRefundAmountVos;
	}
	
	public List<MaxCanRefundAmountVo> buildSingleMaxCanRefundAmountVoList(
			OrderDetailPo orderDetailPo, int productNum) {
		List<MaxCanRefundAmountVo> maxCanRefundAmountVos = new ArrayList<MaxCanRefundAmountVo>();

		MaxCanRefundAmountVo vo1 = new MaxCanRefundAmountVo();
		vo1.setCatalogId(orderDetailPo.getCatalogId());

		if (productNum != 0)
			vo1.setApplyRefundCount(productNum);
		else
			vo1.setApplyRefundCount(orderDetailPo.getProductCount());

		vo1.setMaxCanRefundAmount(getOrderDetailPaidAmountExcludeFreight(
				orderDetailPo, orderDetailPo.getProductCount()));
		vo1.setMaxCanRefundFreight(orderDetailPo.getFreight());

		maxCanRefundAmountVos.add(vo1);

		return maxCanRefundAmountVos;
	}

	public List<MaxCanRefundAmountVo> buildSingleOneByOneMaxCanRefundAmountVoList(
			TradingServiceResp placeOrderResp, Integer refundedCount) {
		List<MaxCanRefundAmountVo> maxCanRefundAmountVos = new ArrayList<MaxCanRefundAmountVo>();

		OrderDetailPo orderDetailPo = placeOrderResp.getOrderList().get(0)
				.getOrderDetailPoList().get(0);
		Integer productCount = orderDetailPo.getProductCount() - refundedCount;

		for (int i = 0; i < productCount; i++) {

			MaxCanRefundAmountVo vo1 = new MaxCanRefundAmountVo();
			vo1.setCatalogId(orderDetailPo.getCatalogId());

			vo1.setApplyRefundCount(1);
			vo1.setMaxCanRefundAuthenticateFee(RefundService
					.getUserAuthenticateFee(orderDetailPo, 1).add(
							i == productCount - 1 ? placeOrderResp
									.getOrderList().get(0)
									.getUserAuthenticateFreightFee()
									: BigDecimal.ZERO));
			vo1.setMaxCanRefundAmount(getOrderDetailPaidAmountExcludeFreight(
					orderDetailPo, 1).add(vo1.getMaxCanRefundAuthenticateFee()));
			vo1.setMaxCanRefundFreight(i == 0 ? orderDetailPo.getFreight()
					: BigDecimal.ZERO);

			maxCanRefundAmountVos.add(vo1);
		}

		return maxCanRefundAmountVos;
	}

	public List<MaxCanRefundAmountVo> buildMaxCanRefundAmountVoList(
			TradingServiceResp placeOrderResp, int productNum) {
		List<MaxCanRefundAmountVo> maxCanRefundAmountVos = new ArrayList<MaxCanRefundAmountVo>();

		OrderDetailPo orderDetailPo1 = placeOrderResp.getOrderList().get(0)
				.getOrderDetailPoList().get(0);

		MaxCanRefundAmountVo vo1 = new MaxCanRefundAmountVo();
		vo1.setCatalogId(orderDetailPo1.getCatalogId());
		
		Long orderId = placeOrderResp.getOrderList().get(0).getOrderId();

		if (productNum != 0)
			vo1.setApplyRefundCount(productNum);
		else
			vo1.setApplyRefundCount(orderDetailPo1.getProductCount());

		vo1.setMaxCanRefundAuthenticateFee(RefundService
				.getUserAuthenticateFee(orderDetailPo1,
						vo1.getApplyRefundCount()));
		vo1.setMaxCanRefundAmount(getOrderDetailPaidAmountExcludeFreight(
				orderDetailPo1, orderDetailPo1.getProductCount()).add(
				vo1.getMaxCanRefundAuthenticateFee()));
		vo1.setMaxCanRefundFreight(orderDetailPo1.getFreight());

		OrderDetailPo orderDetailPo2 = placeOrderResp.getOrderList().get(0)
				.getOrderDetailPoList().get(1);
		MaxCanRefundAmountVo vo2 = new MaxCanRefundAmountVo();
		
		vo2.setCatalogId(orderDetailPo2.getCatalogId());
		vo2.setApplyRefundCount(orderDetailPo2.getProductCount());
		
		if (DeliveryService.isAuthenticateDelivery(orderId)) {

			vo2.setMaxCanRefundAuthenticateFee(RefundService
					.getUserAuthenticateFee(orderDetailPo2,
							vo2.getApplyRefundCount()));
		} else {

			vo2.setMaxCanRefundAuthenticateFee(RefundService
					.getUserAuthenticateFee(orderDetailPo2,
							vo2.getApplyRefundCount())
					.add(productNum == orderDetailPo1.getProductCount() ? placeOrderResp
							.getOrderList().get(0)
							.getUserAuthenticateFreightFee()
							: BigDecimal.ZERO));
		}
		
		vo2.setMaxCanRefundAmount(getOrderDetailPaidAmountExcludeFreight(
				orderDetailPo2, orderDetailPo2.getProductCount()).add(
				vo2.getMaxCanRefundAuthenticateFee()));
		vo2.setMaxCanRefundFreight(orderDetailPo2.getFreight());

		maxCanRefundAmountVos.add(vo1);
		maxCanRefundAmountVos.add(vo2);

		return maxCanRefundAmountVos;
	}
}
